package contacts;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;

import javax.swing.JOptionPane;

import ezvcard.Ezvcard;
import ezvcard.VCard;
import ezvcard.parameters.TelephoneTypeParameter;
import ezvcard.types.AddressType;
import ezvcard.types.BirthdayType;
import ezvcard.types.EmailType;
import ezvcard.types.FormattedNameType;
import ezvcard.types.StructuredNameType;

/**
 * Klasse soll Personen verwalten und Import so wie Exportmoeglichkeiten
 * bereitstellen
 * 
 * @author Michi
 * 
 */
public class Adressbuch {

	/**
	 * Member Data
	 */
	private LinkedList<Person> addressbook;
	@SuppressWarnings("rawtypes")
	private LinkedList toexport = new LinkedList();
	private Connection connection = tools.createConnection.connect();
	private Statement stat;

	@SuppressWarnings("rawtypes")
	public LinkedList getToexport() {
		return toexport;
	}

	@SuppressWarnings("rawtypes")
	public void setToexport(LinkedList toexport) {
		this.toexport = toexport;
	}

	private String name;

	/**
	 * Konstruktor
	 * 
	 * @param name
	 *            Name des Adressbuches
	 */

	public Adressbuch(String name) {
		this.name = name;
		addressbook = new LinkedList<Person>();

	}

	/**
	 * Konstruktor - Legt neues Adressbuch an, gefuellt mit Personen, die aus
	 * vCards importiert werden
	 * 
	 * @param name
	 *            Name des Adressbuches
	 * @param files
	 *            FileArray mit vCards, das uebergeben wird
	 */
	public Adressbuch(String name, File[] files) {

		this.name = name;
		addressbook = new LinkedList<Person>();
		addPerson(files, null);
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public LinkedList<Person> getAdressbook() {
		return addressbook;
	}

	/**
	 * Person einem adressbuch hinzufuegen
	 * 
	 * @param x
	 *            Person die hinzugefuegt wird
	 */
	public void addPerson(Person x) {
		addressbook.add(x);
	}

	/**
	 * Fuegt eine oder mehrere Personen aus vCards dem Adressbuch hinzu
	 * 
	 * @param x
	 *            File Array mit vCards
	 */
	@SuppressWarnings("rawtypes")
	public void addPerson(File[] x, VCardImportWindow vciw) {

		// File Array anlegen in das das uebergebene File Array gespeichert wird
		File[] imports = x;

		// Connection anlegen
		Connection connection = null;

		for (int i = 0; i < imports.length; i++) {

			// File anlegen in welches jeweils die vCards zwischengespeichert
			// werden
			File toDo = imports[i];

			// neues vCard Objekt erstellen
			VCard vcard;
			try {

				// parser der vCard wird gestartet
				// vcard = Ezvcard.parse(toDo).first();
				List vcardlist = Ezvcard.parse(toDo).all();

				for (int p = 0; p < vcardlist.size(); p++) {
					vcard = (VCard) vcardlist.get(p);

					// Ersatz-Konstruktor wird aufgerufen und legt eine neue
					// Person
					// mit Namen und Vornamen an

					Person tempperson;

					if (vcard.getStructuredName().getFamily() != null) {
						tempperson = new Person(vcard.getStructuredName()
								.getFamily(), vcard.getStructuredName()
								.getGiven());
					} else {
						JOptionPane.showMessageDialog(null, "Die vCard \""
								+ imports[i].getName()
								+ "\"konnte nicht gelesen werden",
								"Haaalt! Stop!", JOptionPane.ERROR_MESSAGE);
						continue;
					}
					// FullName wird gesetzt

					tempperson.setFullname(vcard.getStructuredName()
							.getFamily()
							+ " "
							+ vcard.getStructuredName().getGiven());

					// Adresse wird ausgelesen und zusammengesetzt
					if (vcard.getAddresses().size() != 0) {
						tempperson.setAdresse(vcard.getAddresses().get(0)
								.getStreetAddress()
								+ "\n"
								+ vcard.getAddresses().get(0).getPostalCode()
								+ " "
								+ vcard.getAddresses().get(0).getLocality());

						// Einzelne Daten werden zusätzlich gespeichert
						tempperson.setCity(vcard.getAddresses().get(0)
								.getLocality());
						tempperson.setZip(vcard.getAddresses().get(0)
								.getPostalCode());
						tempperson.setStreet(vcard.getAddresses().get(0)
								.getStreetAddress());
					}

					// Da wir nur eine Email Adresse brauchen und speichern
					// lesen
					// wir nur die an Stelle 0 aus
					if (vcard.getEmails().size() != 0) {
						tempperson
								.setEmail(vcard.getEmails().get(0).getValue());
					}

					/**
					 * Eine vCard kann mehrere Nummern enthalten, die in einer
					 * Liste gespeichert sind Je nachdem wie viele Nummern in
					 * einer vCard sind wird der jeweilige Case aufgerufen
					 */
					switch (vcard.getTelephoneNumbers().size()) {

					case 0:

					case 1:

						if (vcard.getTelephoneNumbers().get(0).getTypes()
								.toString().contains("home")) {

							if (vcard.getTelephoneNumbers().get(0).getTypes()
									.toString().contains("fax")) {
								tempperson.setFax(vcard.getTelephoneNumbers()
										.get(0).getValue());
							} else {
								tempperson.setTelefonhome(vcard
										.getTelephoneNumbers().get(0)
										.getValue());
							}

						}

						if (vcard.getTelephoneNumbers().get(0).getTypes()
								.toString().contains("cell")) {

							tempperson.setHandynummer(vcard
									.getTelephoneNumbers().get(0).getValue());
						}
						if (vcard.getTelephoneNumbers().get(0).getTypes()
								.toString().contains("work")) {
							if (vcard.getTelephoneNumbers().get(0).getTypes()
									.toString().contains("fax")) {

							} else {
								tempperson.setTelefonarbeit(vcard
										.getTelephoneNumbers().get(0)
										.getValue());
							}

						}

						break;
					case 2:

						// Stelle 0
						if (vcard.getTelephoneNumbers().get(0).getTypes()
								.toString().contains("home")) {

							if (vcard.getTelephoneNumbers().get(0).getTypes()
									.toString().contains("fax")) {
								tempperson.setFax(vcard.getTelephoneNumbers()
										.get(0).getValue());
							} else {
								tempperson.setTelefonhome(vcard
										.getTelephoneNumbers().get(0)
										.getValue());
							}

						}

						if (vcard.getTelephoneNumbers().get(0).getTypes()
								.toString().contains("cell")) {

							tempperson.setHandynummer(vcard
									.getTelephoneNumbers().get(0).getValue());
						}
						if (vcard.getTelephoneNumbers().get(0).getTypes()
								.toString().contains("work")) {
							if (vcard.getTelephoneNumbers().get(0).getTypes()
									.toString().contains("fax")) {

							} else {
								tempperson.setTelefonarbeit(vcard
										.getTelephoneNumbers().get(0)
										.getValue());
							}

						}

						// Stelle 1

						if (vcard.getTelephoneNumbers().get(1).getTypes()
								.toString().contains("home")) {

							if (vcard.getTelephoneNumbers().get(1).getTypes()
									.toString().contains("fax")) {
								tempperson.setFax(vcard.getTelephoneNumbers()
										.get(1).getValue());
							} else {
								tempperson.setTelefonhome(vcard
										.getTelephoneNumbers().get(1)
										.getValue());
							}

						}

						if (vcard.getTelephoneNumbers().get(1).getTypes()
								.toString().contains("cell")) {

							tempperson.setHandynummer(vcard
									.getTelephoneNumbers().get(1).getValue());
						}
						if (vcard.getTelephoneNumbers().get(1).getTypes()
								.toString().contains("work")) {
							if (vcard.getTelephoneNumbers().get(1).getTypes()
									.toString().contains("fax")) {

							} else {
								tempperson.setTelefonarbeit(vcard
										.getTelephoneNumbers().get(1)
										.getValue());
							}

						}

						break;

					case 3:

						// Stelle 0
						if (vcard.getTelephoneNumbers().get(0).getTypes()
								.toString().contains("home")) {

							if (vcard.getTelephoneNumbers().get(0).getTypes()
									.toString().contains("fax")) {
								tempperson.setFax(vcard.getTelephoneNumbers()
										.get(0).getValue());
							} else {
								tempperson.setTelefonhome(vcard
										.getTelephoneNumbers().get(0)
										.getValue());
							}

						}

						if (vcard.getTelephoneNumbers().get(0).getTypes()
								.toString().contains("cell")) {

							tempperson.setHandynummer(vcard
									.getTelephoneNumbers().get(0).getValue());
						}
						if (vcard.getTelephoneNumbers().get(0).getTypes()
								.toString().contains("work")) {
							if (vcard.getTelephoneNumbers().get(0).getTypes()
									.toString().contains("fax")) {

							} else {
								tempperson.setTelefonarbeit(vcard
										.getTelephoneNumbers().get(0)
										.getValue());
							}

						}

						// Stelle 1

						if (vcard.getTelephoneNumbers().get(1).getTypes()
								.toString().contains("home")) {

							if (vcard.getTelephoneNumbers().get(1).getTypes()
									.toString().contains("fax")) {
								tempperson.setFax(vcard.getTelephoneNumbers()
										.get(1).getValue());
							} else {
								tempperson.setTelefonhome(vcard
										.getTelephoneNumbers().get(1)
										.getValue());
							}

						}

						if (vcard.getTelephoneNumbers().get(1).getTypes()
								.toString().contains("cell")) {

							tempperson.setHandynummer(vcard
									.getTelephoneNumbers().get(1).getValue());
						}
						if (vcard.getTelephoneNumbers().get(1).getTypes()
								.toString().contains("work")) {
							if (vcard.getTelephoneNumbers().get(1).getTypes()
									.toString().contains("fax")) {

							} else {
								tempperson.setTelefonarbeit(vcard
										.getTelephoneNumbers().get(1)
										.getValue());
							}

						}

						// Stelle 2
						if (vcard.getTelephoneNumbers().get(2).getTypes()
								.toString().contains("home")) {

							if (vcard.getTelephoneNumbers().get(2).getTypes()
									.toString().contains("fax")) {
								tempperson.setFax(vcard.getTelephoneNumbers()
										.get(2).getValue());
							} else {
								tempperson.setTelefonhome(vcard
										.getTelephoneNumbers().get(2)
										.getValue());
							}

						}

						if (vcard.getTelephoneNumbers().get(2).getTypes()
								.toString().contains("cell")) {

							tempperson.setHandynummer(vcard
									.getTelephoneNumbers().get(2).getValue());
						}
						if (vcard.getTelephoneNumbers().get(2).getTypes()
								.toString().contains("work")) {
							if (vcard.getTelephoneNumbers().get(2).getTypes()
									.toString().contains("fax")) {

							} else {
								tempperson.setTelefonarbeit(vcard
										.getTelephoneNumbers().get(2)
										.getValue());
							}

						}

						break;

					case 4:

						// Stelle 0
						if (vcard.getTelephoneNumbers().get(0).getTypes()
								.toString().contains("home")) {

							if (vcard.getTelephoneNumbers().get(0).getTypes()
									.toString().contains("fax")) {
								tempperson.setFax(vcard.getTelephoneNumbers()
										.get(0).getValue());
							} else {
								tempperson.setTelefonhome(vcard
										.getTelephoneNumbers().get(0)
										.getValue());
							}

						}

						if (vcard.getTelephoneNumbers().get(0).getTypes()
								.toString().contains("cell")) {

							tempperson.setHandynummer(vcard
									.getTelephoneNumbers().get(0).getValue());
						}
						if (vcard.getTelephoneNumbers().get(0).getTypes()
								.toString().contains("work")) {
							if (vcard.getTelephoneNumbers().get(0).getTypes()
									.toString().contains("fax")) {

							} else {
								tempperson.setTelefonarbeit(vcard
										.getTelephoneNumbers().get(0)
										.getValue());
							}

						}

						// Stelle 1

						if (vcard.getTelephoneNumbers().get(1).getTypes()
								.toString().contains("home")) {

							if (vcard.getTelephoneNumbers().get(1).getTypes()
									.toString().contains("fax")) {
								tempperson.setFax(vcard.getTelephoneNumbers()
										.get(1).getValue());
							} else {
								tempperson.setTelefonhome(vcard
										.getTelephoneNumbers().get(1)
										.getValue());
							}

						}

						if (vcard.getTelephoneNumbers().get(1).getTypes()
								.toString().contains("cell")) {

							tempperson.setHandynummer(vcard
									.getTelephoneNumbers().get(1).getValue());
						}
						if (vcard.getTelephoneNumbers().get(1).getTypes()
								.toString().contains("work")) {
							if (vcard.getTelephoneNumbers().get(1).getTypes()
									.toString().contains("fax")) {

							} else {
								tempperson.setTelefonarbeit(vcard
										.getTelephoneNumbers().get(1)
										.getValue());
							}

						}

						// Stelle 2
						if (vcard.getTelephoneNumbers().get(2).getTypes()
								.toString().contains("home")) {

							if (vcard.getTelephoneNumbers().get(2).getTypes()
									.toString().contains("fax")) {
								tempperson.setFax(vcard.getTelephoneNumbers()
										.get(2).getValue());
							} else {
								tempperson.setTelefonhome(vcard
										.getTelephoneNumbers().get(2)
										.getValue());
							}

						}

						if (vcard.getTelephoneNumbers().get(2).getTypes()
								.toString().contains("cell")) {

							tempperson.setHandynummer(vcard
									.getTelephoneNumbers().get(2).getValue());
						}
						if (vcard.getTelephoneNumbers().get(2).getTypes()
								.toString().contains("work")) {
							if (vcard.getTelephoneNumbers().get(2).getTypes()
									.toString().contains("fax")) {

							} else {
								tempperson.setTelefonarbeit(vcard
										.getTelephoneNumbers().get(2)
										.getValue());
							}

						}

						// Stelle 3

						if (vcard.getTelephoneNumbers().get(3).getTypes()
								.toString().contains("home")) {

							if (vcard.getTelephoneNumbers().get(3).getTypes()
									.toString().contains("fax")) {
								tempperson.setFax(vcard.getTelephoneNumbers()
										.get(3).getValue());
							} else {
								tempperson.setTelefonhome(vcard
										.getTelephoneNumbers().get(3)
										.getValue());
							}

						}

						if (vcard.getTelephoneNumbers().get(3).getTypes()
								.toString().contains("cell")) {

							tempperson.setHandynummer(vcard
									.getTelephoneNumbers().get(3).getValue());
						}
						if (vcard.getTelephoneNumbers().get(3).getTypes()
								.toString().contains("work")) {
							if (vcard.getTelephoneNumbers().get(3).getTypes()
									.toString().contains("fax")) {

							} else {
								tempperson.setTelefonarbeit(vcard
										.getTelephoneNumbers().get(3)
										.getValue());
							}

						}

					}

					// Geburtstag wird ausgelesen
					if (vcard.getBirthday() != null) {
						Date d = vcard.getBirthday().getDate();
						String s = DateToString(d);
						tempperson.setBirthday(s);
						// tempperson.setBirthday(vcard.getBirthday().getDate());

					} else {
						tempperson.setBirthday("");
					}

					// Person wird dem Adressbuch hinzugefügt
					addressbook.add(tempperson);

					// SQL PART BEGIN

					try {

						/**
						 * Verbindungsaufbau zum Server
						 */
						Class.forName("com.mysql.jdbc.Driver");
						connection = DriverManager
								.getConnection("jdbc:mysql://win9142.informatik.uni-wuerzburg.de:3306?user=awesomefireballs&password=jesus");

					} catch (ClassNotFoundException e) {
						e.printStackTrace();
					} catch (SQLException e) {
						e.printStackTrace();

					}

					/**
					 * Erzeugen eines Statements
					 */
					Statement stat = null;

					try {

						/**
						 * Initialisieren eines Statements
						 */
						stat = connection.createStatement();
						stat.executeQuery("use `sopra-ws12-awesome_fireballs`;");

						ResultSet party = stat
								.executeQuery("SELECT idAdress FROM `sopra-ws12-awesome_fireballs`.Adress ORDER BY idadress DESC LIMIT 1;");

						int idAdress = 0;
						while (party.next()) {
							idAdress = party.getInt(1) + 1;
						}

						/**
						 * Erzeugen eines prepared Statements
						 */

						connection.setAutoCommit(false);
						PreparedStatement pstmt = connection
								.prepareStatement("INSERT INTO Adress VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");

						/**
						 * Übergeben aller Informationen der geaddeten vCard /
						 * Person an die Datenbank
						 */
						pstmt.setInt(1, idAdress);
						pstmt.setString(2, tempperson.getVorname());
						pstmt.setString(3, tempperson.getName());
						pstmt.setString(4, tempperson.getStreet());
						pstmt.setString(5, tempperson.getZip());
						pstmt.setString(6, tempperson.getCity());
						pstmt.setString(7, tempperson.getEmail());
						pstmt.setString(8, tempperson.getBirthday().toString());
						pstmt.setString(9, tempperson.getTelefonhome());
						pstmt.setString(10, tempperson.getTelefonarbeit());
						pstmt.setString(11, tempperson.getFax());
						pstmt.setString(12, tempperson.getHandynummer());
						pstmt.addBatch();

						/**
						 * Absenden an die Datenbank
						 */
						PreparedStatement psentrys = connection
								.prepareStatement("INSERT INTO Entrys VALUES( ?, ?, ?)");

						ResultSet entrys = stat
								.executeQuery("SELECT idEntrys FROM `sopra-ws12-awesome_fireballs`.Entrys ORDER BY idEntrys DESC LIMIT 1;");

						int idEntrys = 0;
						while (entrys.next()) {
							idEntrys = entrys.getInt(1) + 1;
						}

						LinkedList<Integer> llbooks = vciw.getSelectedBooks();
						for (int j = 0; j < llbooks.size(); j++) {
							psentrys.setInt(1, idEntrys + j);
							psentrys.setInt(2, idAdress);
							psentrys.setInt(3, llbooks.get(j));
							psentrys.addBatch();
						}

						pstmt.executeBatch();
						psentrys.executeBatch();
						connection.commit();
						connection.setAutoCommit(true);

					} catch (SQLException e1) {
						e1.printStackTrace();
					}

					// SQL PART END

				}
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

	}

	/**
	 * loescht die uebergebene Person
	 * 
	 * @param x
	 *            Person di egeloescht werden soll
	 */

	public void deletePerson(Person x) {
		addressbook.remove(x);
	}

	/**
	 * Gibt Person an der Stelle x zurueck
	 * 
	 * @param x
	 *            Integer Stelle der Liste mit Person die zurueckgegeben werden
	 *            soll
	 * @return Person an der Stelle Integer x
	 */

	public Person getPerson(int x) {
		return addressbook.get(x);

	}

	public int getSize() {
		return addressbook.size();

	}

	/**
	 * Gibt alle Kontakte des Adressbuch als String Array aus
	 * 
	 * @return String Array mit allen Personen des Adressbuches
	 */

	public String[] toStringArray() {

		String[] temp = new String[addressbook.size()];
		for (int i = 0; i < addressbook.size(); i++) {
			temp[i] = addressbook.get(i).getName() + " "
					+ addressbook.get(i).getVorname();
		}

		return temp;

	}

	/**
	 * Gibt alle Personen eines Adressbuches als String zurueck
	 */
	public String toString() {
		String s = "";

		for (int i = 0; i < getSize(); i++) {
			System.out.println(getPerson(i).toString() + "\n" + "\n");
			s = s + getPerson(i).toString() + "\n" + "\n";
		}

		return s;

	}

	/**
	 * Exportiert Person in eine vCard und speichert diese auf die Festplatte
	 * 
	 * @param x
	 *            Person die exportiert werden soll
	 */
	public void exportVCard(Person x, String filePath) {

		String savePath = filePath;
		Writer fw = null;

		String str = "";
		VCard export = new VCard();

		// Name section
		StructuredNameType name = new StructuredNameType();
		name.setFamily(x.getName());
		name.setGiven(x.getVorname());
		export.setStructuredName(name);
		//
		FormattedNameType fn = new FormattedNameType();
		fn.setValue(x.getFullname());
		export.addFormattedName(fn);

		// Adress section
		AddressType address = new AddressType();
		address.setPostalCode(x.getZip());
		address.setStreetAddress(x.getStreet());
		address.setLocality(x.getCity());
		export.addAddress(address);

		// mail section
		EmailType email = new EmailType();
		email.setValue(x.getEmail());
		export.addEmail(email);
		//
		// Telefon section
		if (x.getTelefonhome() != "") {
			export.addTelephoneNumber(x.getTelefonhome(),
					TelephoneTypeParameter.HOME);
		}

		if (x.getTelefonarbeit() != "") {
			export.addTelephoneNumber(x.getTelefonarbeit(),
					TelephoneTypeParameter.WORK);
		}

		if (x.getHandynummer() != "") {
			export.addTelephoneNumber(x.getHandynummer(),
					TelephoneTypeParameter.CELL);
		}

		if (x.getFax() != "") {
			export.addTelephoneNumber(x.getFax(), TelephoneTypeParameter.FAX);
		}

		// Birthday section
		if (x.getBirthday() != null) {
			export.setBirthday(new BirthdayType(StringToDate(x.getBirthday())));
			// export.setBirthday(new BirthdayType(x.getBirthday()));
		}

		str = export.write();

		try {
			fw = new FileWriter(savePath + "/" + x.getVorname() + " "
					+ x.getName() + ".vcf");
			fw.write(str);
		} catch (IOException e) {
			System.err.println("Konnte Datei nicht erstellen");
		} finally {
			if (fw != null)
				try {
					fw.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
		}

	}

	/**
	 * Wandelt Datum in String um
	 * 
	 * @param date
	 *            Datum das gewandelt werdens oll
	 * @return Gibt String des Datums aus
	 */
	@SuppressWarnings("deprecation")
	public String DateToString(Date date) {
		String str = "";
		String a = "";
		if (date.getDate() < 10) {
			a = "0" + date.getDate();
		} else {
			a = "" + date.getDate();
		}

		String b = "";
		if (date.getMonth() < 9) {
			String s = (date.getMonth() + 1) + "";
			b = ("0" + s);
		} else {
			b = (date.getMonth() + 1) + "";
		}

		String c = (date.getYear() + 1900) + "";

		str = c + "-" + b + "-" + a;

		return str;

	}

	/**
	 * Wandelt String in Datum
	 * 
	 * @param Date
	 *            String der in Datum gewandelt werden soll
	 * @return Datum aus dem String
	 */
	public Date StringToDate(String Date) {

		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		Date ret;
		try {
			ret = sdf.parse(Date);
			return ret;
		} catch (ParseException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		}

	}

	public void addexportstoadressbook() {
		try {

			stat = connection.createStatement();

			stat.executeQuery("use `sopra-ws12-awesome_fireballs`;");
			String orString = "";
			for (int i = 0; i < toexport.size(); i++) {
				orString += toexport.get(i);
				if (i != toexport.size() - 1) {
					orString += " OR idAdress = ";
				}
			}

			ResultSet rs = stat
					.executeQuery("SELECT Adress.* FROM Adress WHERE idAdress = "
							+ orString + ";");

			while (rs.next()) {
				Person temp = new Person(rs.getString("lname"),
						rs.getString("fname"), rs.getString("street"),
						rs.getString("zip"), rs.getString("city"),
						rs.getString("email"), rs.getString("bday"),
						rs.getString("telehome"), rs.getString("telework"),
						rs.getString("fax"), rs.getString("cell"),
						rs.getString("idAdress"));
				addressbook.add(temp);
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}

}
